#!/usr/bin/env python

# -*- coding: utf-8 -*-
import glfw
import numpy as np
from OpenGL.GL import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

class OBJ:
    def __init__(self, filename, swapyz=False):
        """Loads a Wavefront OBJ file. """
        self.vertices = []
        self.normals = []
        self.texcoords = []
        self.faces = []

        material = None
        for line in open(filename, "r"):
            if line.startswith('#'): continue
            values = line.split()
            if not values: continue
            if values[0] == 'v':
                v = list(map(float, values[1:4]))
                if swapyz:
                    v = v[0], v[2], v[1]
                self.vertices.append(v)
            elif values[0] == 'vn':
                v = list(map(float, values[1:4]))
                if swapyz:
                    v = v[0], v[2], v[1]
                self.normals.append(v)
            elif values[0] == 'vt':
                self.texcoords.append(list(map(float, values[1:3])))
            elif values[0] in ('usemtl', 'usemat'):
                material = values[1]
            elif values[0] == 'mtllib':
                self.mtl = MTL(values[1])
            elif values[0] == 'f':
                face = []
                texcoords = []
                norms = []
                for v in values[1:]:
                    w = v.split('/')
                    face.append(int(w[0]))
                    if len(w) >= 2 and len(w[1]) > 0:
                        texcoords.append(int(w[1]))
                    else:
                        texcoords.append(0)
                    if len(w) >= 3 and len(w[2]) > 0:
                        norms.append(int(w[2]))
                    else:
                        norms.append(0)
                self.faces.append((face, norms, texcoords, material))
        self.gl_list = glGenLists(1)
        glNewList(self.gl_list, GL_COMPILE)
        glEnable(GL_TEXTURE_2D)
        glFrontFace(GL_CCW)
        for face in self.faces:
            vertices, normals, texture_coords, material = face
            if material!=None:
                mtl = self.mtl[material]
                if 'texture_Kd' in mtl:
                    # use diffuse texmap
                    glBindTexture(GL_TEXTURE_2D, mtl['texture_Kd'])
                else:
                    # just use diffuse colour
                    glColor(*mtl['Kd'])

            glBegin(GL_POLYGON)
            for i in range(len(vertices)):
                if normals[i] > 0:
                    glNormal3fv(self.normals[normals[i] - 1])
                if texture_coords[i] > 0:
                    glTexCoord2fv(self.texcoords[texture_coords[i] - 1])
                glVertex3fv(self.vertices[vertices[i] - 1])
            glEnd()
        glDisable(GL_TEXTURE_2D)
        glEndList()

    def create_bbox(self):
        # self.vertices is not None
        ps=np.array(self.vertices)
        vmin=ps.min(axis=0)
        vmax=ps.max(axis=0)

        self.bbox_center=(vmax+vmin)/2
        self.bbox_half_r=np.max(vmax-vmin)/2


    def create_gl_list(self):
        if self.mtl is not None:
            self.mtl = MTL( *self.mtl )

        self.gl_list = glGenLists(1)
        glNewList(self.gl_list, GL_COMPILE)
        glEnable(GL_TEXTURE_2D)
        glFrontFace(GL_CCW)
        #glCullFace(GL_BACK)
        #glEnable(GL_CULL_FACE)

        for face in self.faces:
            vertices, normals, texture_coords, material = face
 
            mtl = self.mtl[material]
            if 'texture_Kd' in mtl:
                # use diffuse texmap
                glBindTexture(GL_TEXTURE_2D, mtl['texture_Kd'])
            else:
                # just use diffuse colour
                #print(mtl['Kd'],"----")
                glColor(*mtl['Kd'])
 
            glBegin(GL_POLYGON)
            for i in range(len(vertices)):
                if normals[i] > 0:
                    glNormal3fv(self.normals[normals[i] - 1])
                if texture_coords[i] > 0:
                    glTexCoord2fv(self.texcoords[texture_coords[i] - 1])
                glVertex3fv(self.vertices[vertices[i] - 1])
            glEnd()
        glDisable(GL_TEXTURE_2D)
        glEndList()

class OpenGLWidget(QOpenGLWidget):
    def initializeGL(self):
        '''objPath = '3d.obj'
        obj = OBJ(objPath, swapyz=True)
        vertices = np.array(obj.vertices, dtype=np.float32)

        bufferId = glGenBuffers(1)
        glBindBuffer(GL_ARRAY_BUFFER, bufferId)
        glBufferData(GL_ARRAY_BUFFER, vertices.nbytes, vertices, GL_STATIC_DRAW)

        glEnableVertexAttribArray(0)
        glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, None)'''


    def paintGL(self):
        glColor3f(1.0,0.2,0.6)
        #glDrawArrays(GL_TRIANGLES, 0, 3)
        
        #print('draw')
        self.draw()

    def draw(self):
            # ---------------------------------------------------------------
        glBegin(GL_LINES)                    # 开始绘制线段（世界坐标系）
        
        # 以红色绘制x轴
        glColor4f(1.0, 0.0, 0.0, 1.0)        # 设置当前颜色为红色不透明
        glVertex3f(-0.8, 0.0, 0.0)           # 设置x轴顶点（x轴负方向）
        glVertex3f(0.8, 0.0, 0.0)            # 设置x轴顶点（x轴正方向）
        
        # 以绿色绘制y轴
        glColor4f(0.0, 1.0, 0.0, 1.0)        # 设置当前颜色为绿色不透明
        glVertex3f(0.0, -0.8, 0.0)           # 设置y轴顶点（y轴负方向）
        glVertex3f(0.0, 0.8, 0.0)            # 设置y轴顶点（y轴正方向）
        
        # 以蓝色绘制z轴
        glColor4f(0.0, 0.0, 1.0, 1.0)        # 设置当前颜色为蓝色不透明 
        glVertex3f(0.0, 0.0, -0.8)           # 设置z轴顶点（z轴负方向）
        glVertex3f(0.0, 0.0, 0.8)            # 设置z轴顶点（z轴正方向）
        
        glEnd()                              # 结束绘制线段
        
        # ---------------------------------------------------------------
        glBegin(GL_TRIANGLES)                # 开始绘制三角形（z轴负半区）
        
        glColor4f(1.0, 0.0, 0.0, 1.0)        # 设置当前颜色为红色不透明
        glVertex3f(-0.5, -0.366, -0.5)       # 设置三角形顶点
        glColor4f(0.0, 1.0, 0.0, 1.0)        # 设置当前颜色为绿色不透明
        glVertex3f(0.5, -0.366, -0.5)        # 设置三角形顶点
        glColor4f(0.0, 0.0, 1.0, 1.0)        # 设置当前颜色为蓝色不透明
        glVertex3f(0.0, 0.5, -0.5)           # 设置三角形顶点
        
        glEnd()                              # 结束绘制三角形
        
        # ---------------------------------------------------------------
        glFlush()                            # 清空缓冲区，将指令送往硬件立即执行
        
    def drawobj(self):
        glBegin(GL_TRIANGLES)
        for face in self.obj.faces:
            #第一个点的法线，纹理，位置信息
            glNormal3fv(self.obj.normals[face.vertex[0][2]-1].Data)
            glTexCoord2fv(self.obj.texcoords[face.vertex[0][1]-1].Data)
            glVertex3fv(self.obj.vertices[face.vertex[0][0]-1].Data)

            #第二个点的法线，纹理，位置信息
            glNormal3fv(self.obj.normals[face.vertex[1][2]-1].Data)
            glTexCoord2fv(self.obj.texcoords[face.vertex[1][1]-1].Data)
            glVertex3fv(self.obj.vertices[face.vertex[1][0]-1].Data)

            #第三个点的法线，纹理，位置信息
            glNormal3fv(self.obj.normals[face.vertex[2][2]-1].Data)
            glTexCoord2fv(self.obj.texcoords[face.vertex[2][1]-1].Data)
            glVertex3fv(self.obj.vertices[face.vertex[2][0]-1].Data)
        glEnd()



app = QApplication([])
widget = OpenGLWidget()
widget.setAttribute(Qt.WA_TranslucentBackground, True)
fmt=QSurfaceFormat()
fmt.setSamples(8)
widget.setFormat(fmt)
widget.show()
app.exec_()

